﻿//===============================================================================
// Microsoft patterns & practices Enterprise Library
// Core
//===============================================================================
// Copyright © Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Globalization;
using System.Text.RegularExpressions;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Manageability.Adm;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Manageability.Properties;

namespace Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Manageability
{
	/// <summary>
	/// Represents the behavior required to provide Group Policy updates and to publish the 
	/// <see cref="ConfigurationSetting"/> instances associated to a <see cref="NamedConfigurationElement"/>.
	/// </summary>
	/// <remarks>
	/// Subclasses define the implementation necessary to provide manageability for a specific type of configuration
	/// element.
	/// Element providers are usually necessary when dealing with collections of <see cref="NameTypeConfigurationElement"/>,
	/// as the concrete type of the elements in the collections is only known at runtime, and it is possible that 
	/// the elements are defined in 'extension' assemblies.
	/// Element providers are registered with the configuration element types they provide manageability to using 
	/// the <see cref="ConfigurationElementManageabilityProviderAttribute"/> attribute, which is bound to assemblies.
	/// Element providers are also responsible for generating the ADM instructions that describe the policies that can be
	/// used to override the values in the configuration elements. Usually the ADM instructions generated by element providers
	/// consist of a single policy with parts that map to the specific configuration element instance of the type the provider 
	/// manages. This is not mandatory, however, and the ADM instructions generated by element providers must be consistent 
	/// with the ADM structure determined by the section provider that interacts with them.
	/// ADM instructions must be generated for each element instance in a given context, using the elements' names to build
	/// each instruction key.
	/// </remarks>
	/// <seealso cref="ConfigurationSectionManageabilityProvider"/>
	/// <seealso cref="ConfigurationElementManageabilityProviderAttribute"/>
	public abstract class ConfigurationElementManageabilityProvider
	{
		/// <summary>
		/// The name of the value used to hold policy enablement status.
		/// </summary>
		public const String PolicyValueName = ConfigurationSectionManageabilityProvider.PolicyValueName;

		/// <summary>
		/// Initializes a new instance of the <see cref="ConfigurationElementManageabilityProvider"/> class.
		/// </summary>
		protected ConfigurationElementManageabilityProvider()
		{ }

		/// <summary>
		/// Adds the ADM instructions that describe the policies that can be used to override the properties of
		/// a specific instance of the configuration element type managed by the receiver.
		/// </summary>
		/// <param name="contentBuilder">The <see cref="AdmContentBuilder"/> to which the Adm instructions are to be appended.</param>
		/// <param name="configurationObject">The configuration object instance.</param>
		/// <param name="configurationSource">The configuration source from where to get additional configuration
		/// information, if necessary.</param>
		/// <param name="parentKey">The key path for which the generated instructions' keys must be subKeys of.</param>
		/// <remarks>
		/// ADM instructions are generated on a per-instance basis.
		/// </remarks>
		public abstract void AddAdministrativeTemplateDirectives(AdmContentBuilder contentBuilder,
			ConfigurationElement configurationObject,
			IConfigurationSource configurationSource,
			String parentKey);

		/// <summary>
		/// Overrides the <paramref name="configurationObject"/>'s properties with the Group Policy values from the 
		/// registry, if any, and creates the <see cref="ConfigurationSetting"/> instances that describe the 
		/// configurationObject.
		/// </summary>
		/// <param name="configurationObject">The configuration object for instances that must be managed.</param>
		/// <param name="readGroupPolicies"><see langword="true"/> if Group Policy overrides must be applied; otherwise, 
		/// <see langword="false"/>.</param>
		/// <param name="machineKey">The <see cref="IRegistryKey"/> which holds the Group Policy overrides for the 
		/// configuration element at the machine level, or <see langword="null"/> 
		/// if there is no such registry key.</param>
		/// <param name="userKey">The <see cref="IRegistryKey"/> which holds the Group Policy overrides for the 
		/// configuration element at the user level, or <see langword="null"/> 
		/// if there is no such registry key.</param>
		/// <param name="generateWmiObjects"><see langword="true"/> if WMI objects must be generated; otherwise, 
		/// <see langword="false"/>.</param>
		/// <param name="wmiSettings">A collection to where the generated WMI objects are to be added.</param>
		/// <returns><see langword="true"/> if the policy settings do not disable the configuration element, otherwise
		/// <see langword="false"/>.</returns>
		/// <exception cref="ArgumentException">when the type of <paramref name="configurationObject"/> is not 
		/// the type.</exception>
		public abstract bool OverrideWithGroupPoliciesAndGenerateWmiObjects(ConfigurationElement configurationObject,
			bool readGroupPolicies, IRegistryKey machineKey, IRegistryKey userKey,
			bool generateWmiObjects, ICollection<ConfigurationSetting> wmiSettings);

		/// <summary>
		/// Logs an error detected while overriding a configuration object with policy values.
		/// </summary>
		/// <param name="exception">The exception representing the error.</param>
		protected virtual void LogExceptionWhileOverriding(Exception exception)
		{
			ManageabilityExtensionsLogger.LogExceptionWhileOverriding(exception);
		}
	}
}
